package com.example.drools.spring.core.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.example.drools.spring.core.RuleEngine;
import com.example.drools.spring.core.helper.RuleTransformHelper;
import com.example.drools.spring.dao.RuleRepository;
import com.example.drools.spring.entity.DroolEntity;
import com.example.drools.spring.entity.DroolModel;
import com.example.drools.spring.entity.KieResoure;
import com.example.drools.spring.entity.db.Rule;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.drools.compiler.kie.builder.impl.KieContainerImpl;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieScanner;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.springframework.stereotype.Service;

/**
 * @author ddsyw
 * @version 1.0
 * @date 2021/12/29 3:01 下午
 */
@Service
@Slf4j
public class ProductRuleEngineImpl implements RuleEngine {

  @Resource
  private KieFileSystem kieFileSystem;

  @Resource
  private KieSession kieSession;

  @Resource
  private RuleRepository ruleRepository;

  @Resource
  private KieContainerImpl kieContainer;

  @Override
  public <T extends DroolEntity> void executeRuleEngine(T drool) {
    kieSession.insert(drool);
    kieSession.fireAllRules();
  }

  @Override
  public  void executeRuleEngine(Object... drools) {
    if (Objects.isNull(drools)) {
      return;
    }
    List<FactHandle> handleList = new ArrayList<>();
    try {
      for (Object t : drools) {
        if (Objects.nonNull(t)) {
          FactHandle handle = kieSession.insert(t);
          handleList.add(handle);
        }
      }
      //需要删除 执行handle 不然会有影响
      kieSession.fireAllRules();
      handleList.forEach(factHandle -> kieSession.delete(factHandle));
    } catch (Exception e) {
      log.error("execute rule error:{}", ExceptionUtil.getMessage(e));
    }
  }

  @Override
  public void initEngine() {
    //todi nothing
  }

  @Override
  public void refreshEnginRule() {
    Rule ruleDAO = ruleRepository.getOne(1L);
    if (Objects.isNull(ruleDAO) && StringUtils.isBlank(ruleDAO.getRule())) {
      return;
    }
    Optional<DroolModel> droolModelo = RuleTransformHelper.transform(ruleDAO.getRule());
    if (droolModelo.isPresent() && Objects.nonNull(droolModelo.get())) {
      Map<String, KieResoure> kieResoureMap = RuleTransformHelper.transFromDroolModel(
          Arrays.asList(droolModelo.get()));
      if (CollectionUtil.isNotEmpty(kieResoureMap)) {
        kieResoureMap.forEach((key, val)-> {
          kieFileSystem.write(key, val.getResoure());
        });
        KieBuilder kieBuilder = KieServices.Factory.get().newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        kieContainer.updateToKieModule((InternalKieModule) kieBuilder.getKieModule());
      }
    }
  }
}
